/**
 * @description:
 * @author: siwukun
 * @date: 2022/05/30
 */
package com.itheima.stock.service.imp;


import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.google.common.base.Strings;
import com.itheima.stock.common.domian.*;
import com.itheima.stock.face.UserRolePermissionService;
import com.itheima.stock.mapper.SysUserMapper;
import com.itheima.stock.mapper.SysUserRoleMapper;
import com.itheima.stock.pojo.SysPermission;
import com.itheima.stock.pojo.SysRole;
import com.itheima.stock.pojo.SysUser;
import com.itheima.stock.service.UserService;
import com.itheima.stock.utils.IdWorker;
import com.itheima.stock.vo.code.ResponseCode;
import com.itheima.stock.vo.req.LoginReqVo;
import com.itheima.stock.vo.req.UserMenus;
import com.itheima.stock.vo.resp.LoginRespVo;
import com.itheima.stock.vo.resp.PageResult;
import com.itheima.stock.vo.result.R;
import org.apache.commons.lang3.RandomStringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Service
public class UserServiceImpl implements UserService {
    @Autowired
    SysUserMapper sysUserMapper;

    //获取随机id
    @Autowired
    private IdWorker idWorker;
    //密码加密
    @Autowired
    private PasswordEncoder passwordEncoder;

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private SysUserRoleMapper sysUserRoleMapper;

    @Autowired
    private UserRolePermissionService userRolePermissionService;
    /**
     * 生成速记验证码
     *
     * @return r
     */
    @Override
    public R<Map> generateCaptcha() {

        //1.生成4位数字验证码
        String checkCode = RandomStringUtils.randomNumeric(4);
        //获取唯一id
        String nextId = String.valueOf(idWorker.nextId());
        //把验证码存到redis中，设置存活时间1分钟
        redisTemplate.opsForValue().set("ck:" + nextId, checkCode, 60, TimeUnit.SECONDS);
        //封装数据响应给前端
        HashMap<String, String> map = new HashMap<>();
        map.put("code", checkCode);
        map.put("rkey", nextId);
        return R.ok(map);
    }

    @Override
    public R<PageResult<PageInfo>> queryPageUserinfo(UserPageDomain userPageDomain) {
        if (userPageDomain == null) {
            return R.error(ResponseCode.DATA_ERROR.getMessage());
        }
        //单表可以直接使用PageHelper，多表另做处理
        PageHelper.startPage(userPageDomain.getPageNum(), userPageDomain.getPageSize());
        List<UserDomin> list = sysUserMapper.queryPageUserinfo(userPageDomain);
        //把查询的数据进行封装
        PageInfo<UserDomin> pageInfo = new PageInfo<>(list);
        //将pageInfo进行二次封装响应给前端
        PageResult pageResult = new PageResult(pageInfo);
        return R.ok(pageResult);
    }

    @Override
    public R<String> addUserData(SysUser sysUser) {

        if (sysUser == null) {
            return R.error(ResponseCode.DATA_ERROR.getMessage());
        }
        //密码加密
        String encode = passwordEncoder.encode(sysUser.getPassword());
        sysUser.setPassword(encode);
        sysUser.setId(String.valueOf(idWorker.nextId()));
        sysUser.setCreateTime(new Date());
        sysUser.setUpdateTime(new Date());
        sysUser.setCreateId(sysUser.getId());
        sysUser.setUpdateId(sysUser.getId());
        sysUser.setDeleted(1);
        Boolean flag = sysUserMapper.addUserData(sysUser);
        if (!flag) {
            return R.error(ResponseCode.ERROR.getMessage());
        }
        return R.ok(ResponseCode.SUCCESS.getMessage());
    }

    @Override
    public R<UserAndRoles> queryAllUserRoles(String userId) {
        if (Strings.isNullOrEmpty(userId)) {
            return R.error(ResponseCode.DATA_ERROR.getMessage());
        }
        UserAndRoles userAndRoles = new UserAndRoles();
        List<String> ownRoleIds = sysUserMapper.selectRoleByUserId(userId);
        List<SysRole> l = sysUserMapper.queryAllUserRoles(userId);
        userAndRoles.setOwnRoleIds(ownRoleIds.toArray());
        userAndRoles.setAllRole(l);
        if (l == null) {
            return R.error(ResponseCode.NO_RESPONSE_DATA.getMessage());
        }
        return R.ok(userAndRoles);
    }

    @Transactional
    @Override
    public R<String> updateAllUsers(UpdateUserAndRoleInfoDomain u) {

        if (u.getUserId() == null || u.getRoleIds() == null) {
            return R.error(ResponseCode.DATA_ERROR.getMessage());
        }
        //先根据用户ID删除中间表
        boolean flag = true;
        boolean l = sysUserMapper.deleteByPrimaryKeyAllUserRoles(u.getUserId());
        if (l) {
            for (String roleId : u.getRoleIds()) {
                flag = sysUserMapper.insertUserAndRoles(u.getUserId(), roleId, new Date(), String.valueOf(idWorker.nextId()));
            }
            if (flag) {
                return R.ok(ResponseCode.SUCCESS.getMessage());
            }
        }
        return R.error(ResponseCode.NO_RESPONSE_DATA.getMessage());
    }

    @Override
    public R<String> deleteALLUserInfo(List<Long> userIds) {

        if (userIds == null) {
            return R.error(ResponseCode.DATA_ERROR.getMessage());
        }
        int num = 0;
        for (Long userId : userIds) {
//            //先删除中间表
            sysUserRoleMapper.deleteByUserId(userId);
//            if (flag) {
            num = sysUserMapper.deleteByPrimaryKey(userId);
//            }
        }
        if (num > 0) {
            return R.ok(ResponseCode.SUCCESS.getMessage());
        }
        return R.error(ResponseCode.NO_RESPONSE_DATA.getMessage());
    }

    @Override
    public R<SysUser> getUserById(Long id) {
        if (id > 0) {
            return R.error(ResponseCode.DATA_ERROR.getMessage());
        }
        SysUser sysUser = sysUserMapper.getUserById(id);
        if (sysUser == null) {
            return R.error(ResponseCode.NO_RESPONSE_DATA.getMessage());
        }
        return R.ok(sysUser);
    }

    @Override
    public R<String> updateUserById(UserAddDomain userAddDomain) {

        if (userAddDomain ==null){
            return R.error(ResponseCode.DATA_ERROR.getMessage());
        }
        if (userAddDomain.getUsername()==null && userAddDomain.getStatus() != null){
            sysUserMapper.upDateUserStatus(userAddDomain);
             return R.ok(ResponseCode.SUCCESS.getMessage());
        }
        userAddDomain.setUpdateTime(new Date());
        //缓存处理
        boolean flag = userRolePermissionService.cleanUserCacheinfo(userAddDomain);
        if (flag){
            return R.ok(ResponseCode.SUCCESS.getMessage());
        }
        return R.error(ResponseCode.ERROR.getMessage());
    }

    /**
     * 更改用户状态
     * @param id 用户id
     * @param status 用户状态码
     * @return 操作结果
     */
//    @Override
//    public R<String> upDateUserStatus(String id, Integer status) {
//        if (Strings.isNullOrEmpty(id) || status ==null){
//            return R.error(ResponseCode.DATA_ERROR.getMessage());
//        }
//        boolean flag = sysUserMapper.upDateUserStatus(id,status);
//        if (!flag){
//            return R.error(ResponseCode.ERROR.getMessage());
//        }
//        return R.ok(ResponseCode.SUCCESS.getMessage());
//    }

    /**
     * 登录
     *
     * @param vo 请求数据
     * @return LoginRespVo
     */
    @Override
    public R<LoginRespVo> login(LoginReqVo vo) {
        if (vo == null || Strings.isNullOrEmpty(vo.getUsername()) || Strings.isNullOrEmpty(vo.getPassword()) ||
                Strings.isNullOrEmpty(vo.getCode()) || Strings.isNullOrEmpty(vo.getRkey())) {
            //参数不存在
            return R.error(ResponseCode.DATA_ERROR.getMessage());
        }
        //从redis中验证码
        String code = (String) redisTemplate.opsForValue().get("ck:" + vo.getRkey());
        if (code == null || !code.equals(vo.getCode())) {
            return R.error(ResponseCode.SYSTEM_VERIFY_CODE_ERROR.getMessage());
        }
        SysUser user = sysUserMapper.findByUsernamePassword(vo.getUsername());
        //判断账号,密码,验证码是否正确
//        if (user == null || !passwordEncoder.matches(vo.getPassword(), user.getPassword())) {
//            //密码错误
//            return R.error(ResponseCode.SYSTEM_PASSWORD_ERROR.getMessage());
//        }
        //4.2 成功则返回用户的正常信息
        LoginRespVo respVo = new LoginRespVo();
        //保证复制的双方具有共同的属性名称
        BeanUtils.copyProperties(user,respVo);
        //拿到用户的id查询用户对应的权限信息
        List<SysPermission> permissions = sysUserMapper.selectAllUser(user.getId());
        //组装权限树
        List<UserMenus> list = menuEcho(permissions, "0",true);
        //获取菜单按钮集合
        List<String> authBtnPerms = permissions.stream()
                .filter(per -> !Strings.isNullOrEmpty(per.getCode()) && per.getType() == 3)
                .map(per -> per.getCode()).collect(Collectors.toList());
        respVo.setMenus(list);
        respVo.setPermissions(authBtnPerms);
        return R.ok(respVo);
    }

    //组装数据
    private List<UserMenus> menuEcho(List<SysPermission> allUser, String id,Boolean isForMenus) {
        List<UserMenus> list = new ArrayList<>();
        for (SysPermission permission : allUser) {
          if(permission!=null && permission.getType()!=3 || !isForMenus){
              //获取permissionId
              String permissionId = permission.getId();
              //获取pid
              String pid = permission.getPid();
              if (pid!=null){
                  if (pid.equals(id)){
                      UserMenus userMenus = new UserMenus();
                      userMenus.setId(permission.getId());
                      userMenus.setTitle(permission.getTitle());
                      userMenus.setIcon(permission.getIcon());
                      userMenus.setName(permission.getName());
                      userMenus.setChildren(menuEcho(allUser,permissionId,isForMenus));
                      list.add(userMenus);
                  }
              }
          }
        }
        return list;
    }

    @Override
    public boolean updateUserInfo(UserAddDomain userAddDomain){
        boolean flag = sysUserMapper.updateAllUsers(userAddDomain);
        return flag;
    }
}
